/*
 * ModFamGeneral.c
 *
 * Created: 20/03/2012 15:41:28
 *  Author: marionse
 */ 

#include <avr/io.h>

#include <string.h>

#include "FamGeneral.h"
#include "ModSysTimer.h"
#include "AppDesc.h"

/**
* \brief CONSTANTES PRIVEE DU MODULE
*/
#ifndef HB_DEFAULT_PERIOD_US
	#define HB_DEFAULT_PERIOD_US 5000 // un heartbeat toute les 5 secondes
#endif

/**
* \brief VARIABLES PRIVEE DU MODULE
*/
static struct  
{
	TSysTime hb_period; // definit la periode d'envoi du heart-beat en ms
	
	TSysTime last_sys_timer_value;
}fam_general;

/**
* \brief fonction d'initialisation
*/
ERetCode FamGeneralInit( void )
{
	ERetCode lo_ret_code = E_RET_SUCCESS;
	
	/** initialisation des variables privee */
	fam_general.hb_period = HB_DEFAULT_PERIOD_US; // par defaut 5 secondes
	fam_general.last_sys_timer_value = SysTimerGetValue();
	
	/** active l'adc pour mesure interne */
	PRR &= ~(1U << PRADC);
	ADCSRA |= (1<<ADEN);
	ADMUX = (1<<REFS0) | (1<<ADLAR) | (1<<MUX4) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1);
		
	return lo_ret_code;
}

/**
* \brief tick de la boucle principale
*/
ERetCode FamGeneralTick( void )
{
	ERetCode lo_ret_code = E_RET_SUCCESS;
	
	TSysTime l_time_value;
	TRFMsg l_in_msg;	
	
	// envoi d'un signe de vie toute les 5 secondes -> doit etre fait dans le module de la famille general
	l_time_value = SysTimerGetValue();
	if( (0 != fam_general.hb_period) &&
	    (((TSysTime)(l_time_value-fam_general.last_sys_timer_value)) > fam_general.hb_period)
	  )
	{
		SFamMsg hb_msg;

		/** on fait une mesure ADC sur la tension d'alim */
		ADCSRA |= (1<<ADSC);
		while( (ADCSRA & (1<<ADSC)) )
			;
			
		hb_msg.family_id = E_FAM_GENERAL_ID;
		hb_msg.cmd_id = FAM_GEN_CMD_HB_ID;
		hb_msg.len = FAM_GEN_CMD_HB_PAYLOAD_SIZE;
		hb_msg.payload[FAM_GEN_CMD_HB_ARG_BATT_LEVEL_IDX] = ADCH;

		// envoi
		modRFSendMsg( &hb_msg, RF_BRD_ADDR );
		
		fam_general.last_sys_timer_value = l_time_value;
	}
	
	return lo_ret_code;
}

/**
* \brief fonction de traitement des messages radio entrant
*/
ERetCode FamGeneralInMsg( TRFMsg *ip_in_msg )
{
	ERetCode lo_ret_code = E_RET_SUCCESS;
	
	switch( ip_in_msg->msg.cmd_id )
	{
		case FAM_GEN_CMD_HB_ID:
		{
			// verif de la taille payload
			if( FAM_GEN_CMD_HB_PAYLOAD_SIZE == ip_in_msg->msg.len )
			{
				/** cette commande doit etre traitee par l'applicatif si elle le souhaite */
				/** pour gagner en place ram et temps d'appel on passe par une configuration par define */
				#ifdef APP_HAVE_GEN_HB_CALLBACK
					FamGeneralHBCallback( ip_in_msg );
				#endif
			}
			else
			{
				lo_ret_code = E_RET_CMD_INVALID_SIZE;
			}
		}
		break;
		
		case FAM_GEN_CMD_SET_HB_PERIOD_ID:
		{
			/** on modifie localement la periode d'emission */
			if( FAM_GEN_CMD_HB_PERIOD_PAYLOAD_SIZE == ip_in_msg->msg.len )
			{
				fam_general.hb_period = *((TSysTime*)&(ip_in_msg->msg.payload[FAM_GEN_CMD_HB_PERIOD_ARG_VALUE_IDX]));
			}						
			else
			{
				lo_ret_code = E_RET_CMD_INVALID_SIZE;
			}
		}
		break;
		
		case FAM_GEN_CMD_GET_VERSION_ID:
		{
			SFamMsg msg;

			msg.family_id = E_FAM_GENERAL_ID;
			msg.cmd_id = FAM_GEN_CMD_GET_VERSION_RSP_ID;
			msg.len = FAM_GEN_CMD_GET_VERSION_RSP_PAYLOAD_SIZE;
			memcpy( &msg.payload[FAM_GEN_CMD_GET_VERSION_RSP_ARG_VERSION_IDX], 
			        __TIMESTAMP__, FAM_GEN_CMD_GET_VERSION_RSP_ARG_VERSION_SIZE );
					
			modRFSendMsg( &msg, ip_in_msg->src_addr );
		}
		break;
		
		default:
		{
			lo_ret_code = E_RET_CMD_UNKNOWN;
		}
		break;
	}

	return lo_ret_code;
}